<template><div><p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="广播系统" tabindex="-1"><a class="header-anchor" href="#广播系统"><span>广播系统</span></a></h2>
<ul>
<li><a href="#introduction">介绍</a></li>
<li><a href="#server-side-installation">服务器端安装</a>
<ul>
<li><a href="#configuration">配置</a></li>
<li><a href="#reverb">Reverb</a></li>
<li><a href="#pusher-channels">Pusher Channels</a></li>
<li><a href="#ably">Ably</a></li>
</ul>
</li>
<li><a href="#client-side-installation">客户端安装</a>
<ul>
<li><a href="#client-reverb">Reverb</a></li>
<li><a href="#client-pusher-channels">Pusher Channels</a></li>
<li><a href="#client-ably">Ably</a></li>
</ul>
</li>
<li><a href="#concept-overview">概念概述</a>
<ul>
<li><a href="#using-example-application">使用示例应用程序</a></li>
</ul>
</li>
<li><a href="#defining-broadcast-events">定义广播事件</a>
<ul>
<li><a href="#broadcast-name">广播名称</a></li>
<li><a href="#broadcast-data">广播数据</a></li>
<li><a href="#broadcast-queue">广播队列</a></li>
<li><a href="#broadcast-conditions">广播条件</a></li>
<li><a href="#broadcasting-and-database-transactions">广播和数据库事务</a></li>
</ul>
</li>
<li><a href="#authorizing-channels">授权频道</a>
<ul>
<li><a href="#defining-authorization-callbacks">定义授权回调</a></li>
<li><a href="#defining-channel-classes">定义频道类</a></li>
</ul>
</li>
<li><a href="#broadcasting-events">广播事件</a>
<ul>
<li><a href="#only-to-others">仅发送给其他人</a></li>
<li><a href="#customizing-the-connection">自定义连接</a></li>
<li><a href="#anonymous-events">匿名事件</a></li>
</ul>
</li>
<li><a href="#receiving-broadcasts">接收广播</a>
<ul>
<li><a href="#listening-for-events">监听事件</a></li>
<li><a href="#leaving-a-channel">离开频道</a></li>
<li><a href="#namespaces">命名空间</a></li>
</ul>
</li>
<li><a href="#presence-channels">在场频道</a>
<ul>
<li><a href="#authorizing-presence-channels">授权在场频道</a></li>
<li><a href="#joining-presence-channels">加入在场频道</a></li>
<li><a href="#broadcasting-to-presence-channels">广播到在场频道</a></li>
</ul>
</li>
<li><a href="#model-broadcasting">模型广播</a>
<ul>
<li><a href="#model-broadcasting-conventions">模型广播约定</a></li>
<li><a href="#listening-for-model-broadcasts">监听模型广播</a></li>
</ul>
</li>
<li><a href="#client-events">客户端事件</a></li>
<li><a href="#notifications">通知</a></li>
</ul>
<h2 id="介绍" tabindex="-1"><a class="header-anchor" href="#介绍"><span>介绍</span></a></h2>
<p>在许多现代 Web 应用程序中，WebSockets 用于实现实时的、实时更新的用户界面。当服务器上的某些数据更新时，通常会发送一条消息到 WebSocket 连接，以由客户端处理。WebSockets 提供了一种更有效的替代方法，可以连续轮询应用程序服务器以反映 UI 中应该反映的数据更改。</p>
<p>例如，假设你的应用程序能够将用户的数据导出为 CSV 文件并通过电子邮件发送给他们。但是，创建这个 CSV 文件需要几分钟的时间，因此你选择在<a href="https://learnku.com/docs/laravel/11.x/queues" target="_blank" rel="noopener noreferrer">队列</a>中创建和发送 CSV。当 CSV 文件已经创建并发送给用户后，我们可以使用事件广播来分发 <code v-pre>App\Events\UserDataExported</code> 事件，该事件由我们应用程序的 JavaScript 接收。一旦接收到事件，我们可以向用户显示消息，告诉他们他们的 CSV 已通过电子邮件发送给他们，而无需刷新页面。</p>
<p>为了帮助你构建此类功能，Laravel 让通过 WebSocket 连接来「广播」你的服务器端 Laravel <a href="https://learnku.com/docs/laravel/11.x/eventsmd/16677" target="_blank" rel="noopener noreferrer">事件</a> 变得容易。对你的 Laravel 事件进行广播，使你能够在服务器端的 Laravel 应用程序与客户端的 JavaScript 应用程序之间共享相同的事件名称和数据。</p>
<p>广播背后的核心概念很简单：客户端在前端连接到命名通道，而你的 Laravel 应用在后端向这些通道广播事件。这些事件可以包含任何你想要向前端提供的其他数据。</p>
<h4 id="支持的驱动程序" tabindex="-1"><a class="header-anchor" href="#支持的驱动程序"><span>支持的驱动程序</span></a></h4>
<p>默认情况下，Laravel包含了三个服务器端广播驱动程序供你选择：<a href="https://reverb.laravel.com/" target="_blank" rel="noopener noreferrer">Laravel Reverb</a>， <a href="https://pusher.com/channels" target="_blank" rel="noopener noreferrer">Pusher Channels</a>，和 <a href="https://ably.com/" target="_blank" rel="noopener noreferrer">Ably</a>。</p>
<blockquote>
<p><strong>注意</strong><br>
在深入了解事件广播之前，请确保你已阅读了Laravel的<a href="https://learnku.com/docs/laravel/11.x/eventsmd/16677" target="_blank" rel="noopener noreferrer">事件和侦听器</a> 文档。</p>
</blockquote>
<h2 id="服务端安装" tabindex="-1"><a class="header-anchor" href="#服务端安装"><span>服务端安装</span></a></h2>
<p>为了开始使用 Laravel 的事件广播，我们需要在 Laravel 应用程序中进行一些配置，并安装一些包。</p>
<p>事件广播是通过服务端广播驱动程序实现的，该驱动程序广播你的 Laravel 事件，以便 Laravel Echo （一个JavaScript库）可以在浏览器客户端中接收它们。不用担心 —— 我们将逐步介绍安装过程的每个部分。</p>
<h3 id="配置" tabindex="-1"><a class="header-anchor" href="#配置"><span>配置</span></a></h3>
<p>所有应用程序的事件广播配置都存储在<code v-pre>config/broadcasting.php</code>配置文件中。如果你的应用程序中不存在此目录，不用担心；它会在你运行<code v-pre>install:broadcasting</code> Artisan 命令时创建。</p>
<p>Laravel提供了几个开箱即用的广播驱动程序： <a href="https://learnku.com/docs/laravel/11.x/reverbmd" target="_blank" rel="noopener noreferrer">Laravel Reverb</a> ， <a href="https://pusher.com/channels" target="_blank" rel="noopener noreferrer">Pusher Channels</a> ， <a href="https://ably.com/" target="_blank" rel="noopener noreferrer">Ably</a> 以及用于本地开发和调试的 <code v-pre>log</code> 驱动程序。此外，还有一个 <code v-pre>null</code> 驱动程序，允许你在测试期间禁用广播。在 <code v-pre>config/broadcasting.php</code> 配置文件中包含了每个驱动程序的配置示例。</p>
<h4 id="安装" tabindex="-1"><a class="header-anchor" href="#安装"><span>安装</span></a></h4>
<p>默认情况下，新的Laravel应用程序中不会启用广播。你可以执行 <code v-pre>install:broadcasting</code> 这个 Artisan 命令来启用广播：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan install:broadcasting</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><code v-pre>install:broadcasting</code> 命令将创建名为 <code v-pre>config/broadcasting.php</code> 的配置文件。另外，这个命令将创建 <code v-pre>routes/channels.php</code> 文件，你可以在其中注册应用程序的广播授权路由和回调。</p>
<h4 id="队列配置" tabindex="-1"><a class="header-anchor" href="#队列配置"><span>队列配置</span></a></h4>
<p>在对任何事件进行广播之前，你应该首先配置并运行一个<a href="https://learnku.com/docs/laravel/11.x/queuesmd" target="_blank" rel="noopener noreferrer">队列</a>。所有的事件广播均通过队列来实现，以确保你的应用程序的响应时间不会受到广播事件的影响。</p>
<h3 id="reverb" tabindex="-1"><a class="header-anchor" href="#reverb"><span>Reverb</span></a></h3>
<p>当运行 <code v-pre>install:broadcasting</code> 命令时，你会收到安装 <a href="https://learnku.com/docs/laravel/11.x/reverbmd" target="_blank" rel="noopener noreferrer">Laravel Reverb</a> 的提示。当然，您也可以通过 Composer 包管理器手动安装 Reverb 。由于 Reverb 当下处于测试阶段，您需要专门安装测试版：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token function">composer</span> require laravel/reverb:@beta</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>软件包安装完成后，你可以运行 Reverb 的安装命令以发布配置、添加 Reverb 所需的环境变量，并在你的应用中启用事件广播：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan reverb:install</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>你可以在 <a href="https://learnku.com/docs/laravel/11.x/reverb" target="_blank" rel="noopener noreferrer">Reverb 文档</a> 中找到 Reverb 的详细安装和使用说明。</p>
<h3 id="pusher-channels" tabindex="-1"><a class="header-anchor" href="#pusher-channels"><span>Pusher Channels</span></a></h3>
<p>如果你打算使用 <a href="https://pusher.com/channels" target="_blank" rel="noopener noreferrer">Pusher Channels</a> 来广播你的事件，你应该使用 Composer 包管理器安装 Pusher Channels PHP SDK：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token function">composer</span> require pusher/pusher-php-server</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>接下来，你应该在配置文件 <code v-pre>config/broadcasting.php</code> 中配置你的 Pusher Channels 凭据。此文件中已经包含一个 Pusher Channels 的示例配置，让你可以快速指定 key 、 secret 和 应用 ID 。通常，你应该在应用的 <code v-pre>.env</code> 文件中配置你的推送通道凭据：</p>
<div class="language-ini line-numbers-mode" data-highlighter="prismjs" data-ext="ini" data-title="ini"><pre v-pre class="language-ini"><code><span class="line"><span class="token key attr-name">PUSHER_APP_ID</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">your-pusher-app-id</span>"</span></span>
<span class="line"><span class="token key attr-name">PUSHER_APP_KEY</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">your-pusher-key</span>"</span></span>
<span class="line"><span class="token key attr-name">PUSHER_APP_SECRET</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">your-pusher-secret</span>"</span></span>
<span class="line"><span class="token key attr-name">PUSHER_HOST</span><span class="token punctuation">=</span></span>
<span class="line"><span class="token key attr-name">PUSHER_PORT</span><span class="token punctuation">=</span><span class="token value attr-value">443</span></span>
<span class="line"><span class="token key attr-name">PUSHER_SCHEME</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">https</span>"</span></span>
<span class="line"><span class="token key attr-name">PUSHER_APP_CLUSTER</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">mt1</span>"</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>config/broadcasting.php</code> 文件的 <code v-pre>pusher</code> 配置还允许你指定 Channels 支持的其他 <code v-pre>options</code>，例如集群。</p>
<p>接下来，你需要在你的 <code v-pre>.env</code> 文件中将 <code v-pre>BROADCAST_CONNECTION</code> 更改为 <code v-pre>pusher</code>：</p>
<div class="language-ini line-numbers-mode" data-highlighter="prismjs" data-ext="ini" data-title="ini"><pre v-pre class="language-ini"><code><span class="line"><span class="token key attr-name">BROADCAST_CONNECTION</span><span class="token punctuation">=</span><span class="token value attr-value">pusher</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>最后，你已经做好安装和配置 <a href="#client-side-installation">Laravel Echo</a>的准备，它将在客户端接收广播事件。</p>
<h3 id="ably" tabindex="-1"><a class="header-anchor" href="#ably"><span>Ably</span></a></h3>
<blockquote>
<p><strong>注意</strong><br>
下面的文档介绍了如何在 「Pusher 兼容」 模式下使用 Ably 。然而，Ably 团队推荐并维护了一个能够利用 Ably 独特功能的广播器和 Echo 客户端。 Ably 维护的驱动程序的更多使用信息，请<a href="https://github.com/ably/laravel-broadcaster" target="_blank" rel="noopener noreferrer">参考 Ably 的 Laravel 广播文档</a> 。</p>
</blockquote>
<p>如果你打算使用 <a href="https://ably.com/" target="_blank" rel="noopener noreferrer">Ably</a> 广播你的事件，你应该使用 Composer 包管理器安装 Ably PHP SDK ：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token function">composer</span> require ably/ably-php</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>接下来，你应该在配置文件 config/broadcasting.php 中配置你的 Ably 凭据。此文件中已经包含一个 Ably 的示例配置，让你快速指定密钥。通常，这个值应通过 <code v-pre>ABLY_KEY</code> <a href="https://learnku.com/docs/laravel/11.x/configurationmd#environment-configuration" target="_blank" rel="noopener noreferrer">环境变量</a> 设置：</p>
<div class="language-ini line-numbers-mode" data-highlighter="prismjs" data-ext="ini" data-title="ini"><pre v-pre class="language-ini"><code><span class="line"><span class="token key attr-name">ABLY_KEY</span><span class="token punctuation">=</span><span class="token value attr-value">your-ably-key</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>接下来，你需要在你的 <code v-pre>.env</code> 文件中将 <code v-pre>BROADCAST_CONNECTION</code> 更改为 <code v-pre>ably</code></p>
<div class="language-ini line-numbers-mode" data-highlighter="prismjs" data-ext="ini" data-title="ini"><pre v-pre class="language-ini"><code><span class="line"><span class="token key attr-name">BROADCAST_CONNECTION</span><span class="token punctuation">=</span><span class="token value attr-value">ably</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>最后，你已经做好安装和配置 <a href="#client-side-installation">Laravel Echo</a> 的准备，它将在客户端接收广播事件。</p>
<h2 id="客户端安装" tabindex="-1"><a class="header-anchor" href="#客户端安装"><span>客户端安装</span></a></h2>
<h3 id="reverb-1" tabindex="-1"><a class="header-anchor" href="#reverb-1"><span>Reverb</span></a></h3>
<p><a href="https://github.com/laravel/echo" target="_blank" rel="noopener noreferrer">Laravel Echo</a> 是一个 JavaScript 库，可以轻松订阅频道并监听服务器端广播驱动程序广播的事件。你可以通过 NPM 包管理器安装 Echo 。在本示例中，我们还将安装 <code v-pre>pusher-js</code> 包，因为 Reverb 在 WebSocket 订阅，频道和消息方面使用了 Pusher 协议。</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token function">npm</span> <span class="token function">install</span> --save-dev laravel-echo pusher-js</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>一旦安装了 Echo，你就能够在应用程序的 JavaScript 中创建一个全新的 Echo 实例。一个不错的操作位置是在 Laravel 框架所包含的“resources/js/bootstrap.js”文件的底部。默认情况下，此文件中已经包含了一个 Echo 配置示例——你只需要取消其注释，并将 <code v-pre>broadcaster</code> 配置选项更新为 <code v-pre>reverb</code> ：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line"><span class="token keyword">import</span> Echo <span class="token keyword">from</span> <span class="token string">'laravel-echo'</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">import</span> Pusher <span class="token keyword">from</span> <span class="token string">'pusher-js'</span><span class="token punctuation">;</span></span>
<span class="line">window<span class="token punctuation">.</span>Pusher <span class="token operator">=</span> Pusher<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">window<span class="token punctuation">.</span>Echo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    <span class="token literal-property property">broadcaster</span><span class="token operator">:</span> <span class="token string">'reverb'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">key</span><span class="token operator">:</span> <span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VITE_REVERB_APP_KEY</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">wsHost</span><span class="token operator">:</span> <span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VITE_REVERB_HOST</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">wsPort</span><span class="token operator">:</span> <span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VITE_REVERB_PORT</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">wssPort</span><span class="token operator">:</span> <span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VITE_REVERB_PORT</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">forceTLS</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VITE_REVERB_SCHEME</span> <span class="token operator">??</span> <span class="token string">'https'</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token string">'https'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">enabledTransports</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'ws'</span><span class="token punctuation">,</span> <span class="token string">'wss'</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>接下来，你应该编译应用程序的资源：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token function">npm</span> run build</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p><strong>警告</strong><br>
Laravel Echo 的 <code v-pre>reverb</code> 广播器需要 laravel-echo v1.16.0+</p>
</blockquote>
<h3 id="pusher-channels-1" tabindex="-1"><a class="header-anchor" href="#pusher-channels-1"><span>Pusher Channels</span></a></h3>
<p><a href="https://github.com/laravel/echo" target="_blank" rel="noopener noreferrer">Laravel Echo</a> 是一个JavaScript库，它可以轻松订阅频道并收听服务器端广播驱动程序广播的事件。Echo 还利用 <code v-pre>pusher-js</code> NPM 包为 WebSocket 订阅、频道和消息实现 Pusher 协议。</p>
<p><code v-pre>install:broadcasting</code> Artisan 命令会自动为你安装 <code v-pre>laravel-echo</code> 和 <code v-pre>pusher-js</code> ；当然，你可以也可以使用 NPM 手动安装</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token function">npm</span> <span class="token function">install</span> --save-dev laravel-echo pusher-js</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>一旦安装了 Echo ，你就能够在应用程序的 JavaScript 中创建一个全新的 Echo 实例。<code v-pre>install:broadcasting</code> 命令会在 <code v-pre>resources/js/echo.js</code> 创建一个 Echo 配置文件；然而，此文件中的默认配置是为 Laravel Reverb 准备的。你可以复制以下配置，将你的配置转换为 Pusher ：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line"><span class="token keyword">import</span> Echo <span class="token keyword">from</span> <span class="token string">'laravel-echo'</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">import</span> Pusher <span class="token keyword">from</span> <span class="token string">'pusher-js'</span><span class="token punctuation">;</span></span>
<span class="line">window<span class="token punctuation">.</span>Pusher <span class="token operator">=</span> Pusher<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">window<span class="token punctuation">.</span>Echo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    <span class="token literal-property property">broadcaster</span><span class="token operator">:</span> <span class="token string">'pusher'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">key</span><span class="token operator">:</span> <span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VITE_PUSHER_APP_KEY</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">cluster</span><span class="token operator">:</span> <span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VITE_PUSHER_APP_CLUSTER</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">forceTLS</span><span class="token operator">:</span> <span class="token boolean">true</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>接下来，你应该在应用程序的 <code v-pre>. env</code> 文件中为 Pusher 的环境变量定义适当的值。如果这些变量在你的 <code v-pre>.env</code> 文件中不存在，你应该添加它们：</p>
<div class="language-ini line-numbers-mode" data-highlighter="prismjs" data-ext="ini" data-title="ini"><pre v-pre class="language-ini"><code><span class="line"><span class="token key attr-name">PUSHER_APP_ID</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">your-pusher-app-id</span>"</span></span>
<span class="line"><span class="token key attr-name">PUSHER_APP_KEY</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">your-pusher-key</span>"</span></span>
<span class="line"><span class="token key attr-name">PUSHER_APP_SECRET</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">your-pusher-secret</span>"</span></span>
<span class="line"><span class="token key attr-name">PUSHER_HOST</span><span class="token punctuation">=</span></span>
<span class="line"><span class="token key attr-name">PUSHER_PORT</span><span class="token punctuation">=</span><span class="token value attr-value">443</span></span>
<span class="line"><span class="token key attr-name">PUSHER_SCHEME</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">https</span>"</span></span>
<span class="line"><span class="token key attr-name">PUSHER_APP_CLUSTER</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">mt1</span>"</span></span>
<span class="line"></span>
<span class="line"><span class="token key attr-name">VITE_APP_NAME</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">${APP_NAME}</span>"</span></span>
<span class="line"><span class="token key attr-name">VITE_PUSHER_APP_KEY</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">${PUSHER_APP_KEY}</span>"</span></span>
<span class="line"><span class="token key attr-name">VITE_PUSHER_HOST</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">${PUSHER_HOST}</span>"</span></span>
<span class="line"><span class="token key attr-name">VITE_PUSHER_PORT</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">${PUSHER_PORT}</span>"</span></span>
<span class="line"><span class="token key attr-name">VITE_PUSHER_SCHEME</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">${PUSHER_SCHEME}</span>"</span></span>
<span class="line"><span class="token key attr-name">VITE_PUSHER_APP_CLUSTER</span><span class="token punctuation">=</span><span class="token value attr-value">"<span class="token inner-value">${PUSHER_APP_CLUSTER}</span>"</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>根据应用程序的需要调整 Echo 配置后，你就可以编译应用程序的资源了：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token function">npm</span> run build</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
要了解有关编译应用程序的 JavaScript 资源的更多信息，请参阅 <a href="https://learnku.com/docs/laravel/11.x/vitemd" target="_blank" rel="noopener noreferrer">Vite</a></p>
</blockquote>
<h4 id="使用现有客户端实例" tabindex="-1"><a class="header-anchor" href="#使用现有客户端实例"><span>使用现有客户端实例</span></a></h4>
<p>如果你希望 Echo 使用一个你已经进行了预配置的 Pusher Channels 客户端实例，你可以通过 <code v-pre>client</code> 配置选项来传递给 Echo：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line"><span class="token keyword">import</span> Echo <span class="token keyword">from</span> <span class="token string">'laravel-echo'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">import</span> Pusher <span class="token keyword">from</span> <span class="token string">'pusher-js'</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">const</span> options <span class="token operator">=</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token literal-property property">broadcaster</span><span class="token operator">:</span> <span class="token string">'pusher'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">key</span><span class="token operator">:</span> <span class="token string">'your-pusher-channels-key'</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">window<span class="token punctuation">.</span>Echo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    <span class="token operator">...</span>options<span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">client</span><span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">Pusher</span><span class="token punctuation">(</span>options<span class="token punctuation">.</span>key<span class="token punctuation">,</span> options<span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="ably-1" tabindex="-1"><a class="header-anchor" href="#ably-1"><span>Ably</span></a></h3>
<blockquote>
<p><strong>注意</strong><br>
下面的文档介绍了如何在 「Pusher 兼容」 模式下使用 Ably 。然而，Ably 团队推荐并维护了一个能够利用 Ably 独特功能的广播器和 Echo 客户端。 Ably 维护的驱动程序的更多使用信息，请 <a href="https://github.com/ably/laravel-broadcaster" target="_blank" rel="noopener noreferrer">参考 Ably 的 Laravel 广播文档</a> 。</p>
</blockquote>
<p><a href="https://github.com/laravel/echo" target="_blank" rel="noopener noreferrer">Laravel Echo</a> 是一个 JavaScript 库，它可以轻松订阅频道并收听服务器端广播驱动程序广播的事件。Echo 还利用 <code v-pre>pusher-js</code> NPM 包为 WebSocket 订阅、频道和消息实现 Pusher 协议。</p>
<p><code v-pre>install:broadcasting</code> Artisan 命令会自动为你安装 <code v-pre>laravel-echo</code> 和 <code v-pre>pusher-js</code> ；当然，你可以也可以使用 NPM 手动安装</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token function">npm</span> <span class="token function">install</span> --save-dev laravel-echo pusher-js</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><strong>在继续之前，你应该在你的 Ably 应用设置中启用 Pusher 协议支持。你可以在你的 Ably 应用设置仪表板的 「协议适配器设置」 部分中启用此功能。</strong></p>
<p>安装Echo后，你就可以在应用程序的 JavaScript 中创建一个新的 Echo 实例了。<code v-pre>install:broadcasting</code> 命令会在 <code v-pre>resources/js/echo.js</code> 处创建一个Echo配置文件；然而，此文件中的默认配置是为 Laravel Reverb 准备的。你可以复制以下配置，将你的配置转换为 Ably ：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line"><span class="token keyword">import</span> Echo <span class="token keyword">from</span> <span class="token string">'laravel-echo'</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">import</span> Pusher <span class="token keyword">from</span> <span class="token string">'pusher-js'</span><span class="token punctuation">;</span></span>
<span class="line">window<span class="token punctuation">.</span>Pusher <span class="token operator">=</span> Pusher<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">window<span class="token punctuation">.</span>Echo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    <span class="token literal-property property">broadcaster</span><span class="token operator">:</span> <span class="token string">'pusher'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">key</span><span class="token operator">:</span> <span class="token keyword">import</span><span class="token punctuation">.</span>meta<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">VITE_ABLY_PUBLIC_KEY</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">wsHost</span><span class="token operator">:</span> <span class="token string">'realtime-pusher.ably.io'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">wsPort</span><span class="token operator">:</span> <span class="token number">443</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">disableStats</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token literal-property property">encrypted</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>你可能已经注意到了，我们的 Ably Echo 配置引用了一个 <code v-pre>VITE_ABLY_PUBLIC_KEY</code> 的环境变量。该变量的值应该是你的 Ably 公钥。你的公钥是出现在 Ably 密钥的 <code v-pre>:</code> 字符之前的部分。</p>
<p>根据需要调整Echo配置后，你可以编译应用程序的资源了：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token function">npm</span> run dev</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
要了解有关编译应用程序的 JavaScript 资源的更多信息，请参阅 <a href="https://learnku.com/docs/laravel/11.x/vite" target="_blank" rel="noopener noreferrer">Vite</a></p>
</blockquote>
<h2 id="概念概述" tabindex="-1"><a class="header-anchor" href="#概念概述"><span>概念概述</span></a></h2>
<p>Laravel 的事件广播允许你使用基于驱动程序的 WebSocket 方法，将服务器端 Laravel 事件广播到客户端的 JavaScript 应用程序。目前，Laravel 附带了 <a href="https://pusher.com/channels" target="_blank" rel="noopener noreferrer">Pusher Channels</a> 和 <a href="https://ably.com/" target="_blank" rel="noopener noreferrer">Ably</a> 驱动程序。使用 <a href="#client-side-installation">Laravel Echo</a> JavaScript 包可以在客户端轻松使用这些事件</p>
<p>事件通过 「频道」 广播，可以指定为公共或私有。任何访问你的应用程序的用户都可以订阅公共频道，无需进行身份验证或授权；但是，要订阅私有频道，用户必须经过身份验证和授权才能收听该频道。</p>
<h3 id="使用示例应用程序" tabindex="-1"><a class="header-anchor" href="#使用示例应用程序"><span>使用示例应用程序</span></a></h3>
<p>在深入探讨事件广播的每个组件之前，让我们以电子商务商店为例，进行高层次的概述。</p>
<p>在我们的应用程序中，假设我们有一个页面允许用户查看他们订单的配送状态。同时假设当应用程序处理配送状态更新时，会触发一个 <code v-pre>OrderShipmentStatusUpdated</code> 事件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Events<span class="token punctuation">\</span>OrderShipmentStatusUpdated</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">OrderShipmentStatusUpdated</span><span class="token operator">::</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token variable">$order</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="shouldbroadcast-接口" tabindex="-1"><a class="header-anchor" href="#shouldbroadcast-接口"><span><code v-pre>ShouldBroadcast</code> 接口</span></a></h4>
<p>当用户查看他们的某个订单时，我们不希望他们必须刷新页面来查看状态更新。相反，我们希望在创建更新时将其广播到应用程序。因此，我们需要用 <code v-pre>ShouldBroadcast</code> 接口标记 <code v-pre>OrderShipmentStatusUpdated</code> 事件。这将指示 Laravel 在事件触发时进行广播：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Events</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Order</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>Channel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>InteractsWithSockets</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PresenceChannel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>ShouldBroadcast</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Queue<span class="token punctuation">\</span>SerializesModels</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">OrderShipmentStatusUpdated</span> <span class="token keyword">implements</span> <span class="token class-name">ShouldBroadcast</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 订单实例。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token punctuation">\</span>App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Order</span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token variable">$order</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>ShouldBroadcast</code> 接口要求我们的事件定义一个 <code v-pre>broadcastOn</code> 方法。此方法负责返回事件应该广播的频道。生成的事件类上已经定义了这个方法的空存根，所以我们只需要填写它的详细信息。我们只希望订单的创建者能够查看状态更新，因此我们将在与订单绑定的私有频道上广播事件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>Channel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PrivateChannel</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取事件应该广播的频道。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastOn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">Channel</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">PrivateChannel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders.'</span><span class="token operator">.</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">order</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你希望事件在多个频道上广播，你可以返回一个<code v-pre>array</code>数组：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PrivateChannel</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取应播放这个事件的频道。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;int, \Illuminate\Broadcasting\Channel></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastOn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token keyword">new</span> <span class="token class-name">PrivateChannel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders.'</span><span class="token operator">.</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">order</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="授权频道" tabindex="-1"><a class="header-anchor" href="#授权频道"><span>授权频道</span></a></h4>
<p>请记住，用户必须被授权才能收听私有频道。我们可以在应用程序的<code v-pre>routes/channels.php</code>文件中定义我们的频道授权规则。在这个例子中，我们需要验证任何试图收听私有 <code v-pre>orders.1</code> 频道的用户实际上是订单的创建者：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Order</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders.{orderId}'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token keyword type-hint">int</span> <span class="token variable">$orderId</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span> <span class="token operator">===</span> <span class="token class-name static-context">Order</span><span class="token operator">::</span><span class="token function">findOrNew</span><span class="token punctuation">(</span><span class="token variable">$orderId</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token property">user_id</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>channel</code> 方法接受两个参数: 频道的名称和一个回调函数，该回调函数返回<code v-pre>true</code> 或者 <code v-pre>false</code>，用于指示用户是否有权限收听该频道。</p>
<p>所有的授权回调函数都将当前已认证的用户作为它们的第一个参数，并将任何附加的通配符参数作为后续参数。在这个例子中，我们使用 <code v-pre>{orderId}</code> 占位符来表示频道名称中的「ID」 部分是一个通配符</p>
<h4 id="监听事件广播" tabindex="-1"><a class="header-anchor" href="#监听事件广播"><span>监听事件广播</span></a></h4>
<p>接下来, 我们只需在我们的 JavaScript 应用程序中监听事件即可. 我们可以使用 <a href="#client-side-installation">Laravel Echo</a>来实现这一点。首先，我们将使用 <code v-pre>private</code> 方法订阅私有频道。然后，我们可以使用 <code v-pre>listen</code> 方法监听 <code v-pre>OrderShipmentStatusUpdated</code> 事件。默认情况下，事件的所有公共属性都会包含在广播事件中：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">private</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">orders.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>orderId<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string">'OrderShipmentStatusUpdated'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>order<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="定义广播事件" tabindex="-1"><a class="header-anchor" href="#定义广播事件"><span>定义广播事件</span></a></h2>
<p>要通知 Laravel 给定事件应该被广播，你必须在事件类上实现 <code v-pre>Illuminate\Contracts\Broadcasting\ShouldBroadcast</code> 接口。该接口已经导入到了框架生成的所有事件类中，因此你可以轻松地将其添加到任何事件中。</p>
<p><code v-pre>ShouldBroadcast</code>接口要求你实现一个单一的方法：<code v-pre>broadcastOn</code>。<code v-pre>broadcastOn</code> 方法应该返回一个频道或者一个频道的数组，事件应该在这些频道上被广播。这些频道应该是 <code v-pre>Channel</code>, <code v-pre>PrivateChannel</code>, 或 <code v-pre>PresenceChannel</code> 的实例。<code v-pre>Channel</code> 的实例代表任何用户都可以订阅的公共频道，而 <code v-pre>PrivateChannels</code> 和 <code v-pre>PresenceChannels</code> 代表需要 <a href="#authorizing-channels">频道授权</a> 的私有频道：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Events</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>Channel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>InteractsWithSockets</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PresenceChannel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PrivateChannel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>ShouldBroadcast</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Queue<span class="token punctuation">\</span>SerializesModels</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">ServerCreated</span> <span class="token keyword">implements</span> <span class="token class-name">ShouldBroadcast</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">SerializesModels</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 创建一个新的事件实例。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__construct</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token keyword">public</span> <span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 获取事件应该广播到哪些频道。</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;int, \Illuminate\Broadcasting\Channel></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastOn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token keyword">new</span> <span class="token class-name">PrivateChannel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'user.'</span><span class="token operator">.</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">user</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在实现了 <code v-pre>ShouldBroadcast</code> 接口之后，你只需要像平常一样 <a href="https://learnku.com/docs/laravel/11.x/eventsmd" target="_blank" rel="noopener noreferrer">触发事件</a>。一旦事件被触发，一个 <a href="https://learnku.com/docs/laravel/11.x/queuesmd" target="_blank" rel="noopener noreferrer">队列任务</a> 将自动使用你指定的广播驱动来广播事件。</p>
<h3 id="广播名称" tabindex="-1"><a class="header-anchor" href="#广播名称"><span>广播名称</span></a></h3>
<p>默认情况下，Laravel 会使用事件的类名进行广播。但是，你可以通过在事件中定义一个 <code v-pre>broadcastAs</code> 方法来自定义广播名称：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 事件的广播名字</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastAs</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">string</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token string single-quoted-string">'server.created'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你使用 <code v-pre>broadcastAs</code> 方法自定义了广播名称，你应该确保你的监听器是以一个前导 <code v-pre>.</code> 字符注册的。这可以通知 Echo 不要将应用的命名空间添加到事件前面：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token operator">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'.server.created'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token operator">...</span><span class="token operator">.</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="广播数据" tabindex="-1"><a class="header-anchor" href="#广播数据"><span>广播数据</span></a></h3>
<p>当一个事件被广播时，所有的 <code v-pre>public</code> 属性会被自动序列化并作为事件负载进行广播，允许你从你的 JavaScript 应用中访问它的任何公共数据。例如，如果你的事件有一个公共的 <code v-pre>$user</code> 属性，它包含一个 Eloquent 模型，那么事件的广播负载将会是：</p>
<div class="language-json line-numbers-mode" data-highlighter="prismjs" data-ext="json" data-title="json"><pre v-pre class="language-json"><code><span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token property">"user"</span><span class="token operator">:</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token property">"id"</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"Patrick Stewart"</span></span>
<span class="line">        ...</span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然而，如果你希望对你的广播负载有更细粒度的控制，你可以在你的事件中添加一个 <code v-pre>broadcastWith</code> 方法。这个方法应该返回一个数组，数组中包含你希望作为事件负载进行广播的数据：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取将要广播的数据</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;string, mixed></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastWith</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'id'</span> <span class="token operator">=></span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">user</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="广播队列" tabindex="-1"><a class="header-anchor" href="#广播队列"><span>广播队列</span></a></h3>
<p>默认情况下，每个广播事件都会被放置在你的 <code v-pre>queue.php</code> 配置文件中指定的默认队列的默认队列连接上。你可以通过在你的事件类上定义 <code v-pre>connection</code> 和 <code v-pre>queue</code> 属性来自定义广播者使用的队列连接和名称：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 当广播事件时使用的队列连接的名字</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">string</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token variable">$connection</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'redis'</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 广播任务放置的队列的名称</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">string</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token variable">$queue</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'default'</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>或者，你也可以通过在你的事件中定义一个 <code v-pre>broadcastQueue</code> 方法来自定义队列名称：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> *  广播任务放置的队列的名称</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastQueue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">string</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token string single-quoted-string">'default'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你希望通过使用 <code v-pre>sync</code> 队列而不是默认的队列驱动程序来广播你的事件，你可以实现 <code v-pre>ShouldBroadcastNow</code> 接口而不是 <code v-pre>ShouldBroadcast</code> 接口：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>ShouldBroadcastNow</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">OrderShipmentStatusUpdated</span> <span class="token keyword">implements</span> <span class="token class-name">ShouldBroadcastNow</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="广播条件" tabindex="-1"><a class="header-anchor" href="#广播条件"><span>广播条件</span></a></h3>
<p>有时你希望你的事件只在给定的条件为真时广播。你可以通过在你的事件类中添加一个 <code v-pre>broadcastWhen</code> 方法来定义这些条件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 确定此事件是否应该广播。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastWhen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">bool</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">order</span><span class="token operator">-></span><span class="token property">value</span> <span class="token operator">></span> <span class="token number">100</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="广播和数据库事务" tabindex="-1"><a class="header-anchor" href="#广播和数据库事务"><span>广播和数据库事务</span></a></h4>
<p>当在数据库事务中分派广播事件时，它们可能会在数据库事务提交之前被队列处理。当这种情况发生时，你在数据库事务期间对模型或数据库记录进行的任何更新可能还没有在数据库中反映出来。此外，在事务期间创建的任何模型或数据库记录可能不存在于数据库中。如果你的事件依赖于这些模型，当处理广播事件的工作时可能会发生意外的错误。</p>
<p>如果你的队列连接的 <code v-pre>after_commit</code> 配置选项设置为 <code v-pre>false</code>，你仍然可以指示特定的广播事件应在所有打开的数据库事务被提交后分派，方法是在事件类上实现 <code v-pre>ShouldDispatchAfterCommit</code> 接口：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Events</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>ShouldBroadcast</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Events<span class="token punctuation">\</span>ShouldDispatchAfterCommit</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Queue<span class="token punctuation">\</span>SerializesModels</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">ServerCreated</span> <span class="token keyword">implements</span> <span class="token class-name">ShouldBroadcast</span><span class="token punctuation">,</span> ShouldDispatchAfterCommit</span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">SerializesModels</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
更多关于应对这些问题的方法，请查看有关<a href="https://learnku.com/docs/laravel/11.x/queuesmd#jobs-and-database-transactions" target="_blank" rel="noopener noreferrer">队列作业和数据库事务</a>的文档。</p>
</blockquote>
<h2 id="授权频道-1" tabindex="-1"><a class="header-anchor" href="#授权频道-1"><span>授权频道</span></a></h2>
<p>私有频道要求你授权当前认证的用户能实际上在频道上进行监听。这可以通过向 Laravel 应用程序发送带有频道名称的 HTTP 请求，并让应用程序决定用户是否可以在该频道上进行监听来实现。当使用 <a href="#client-side-installation">Laravel Echo</a> 时，授权订阅私有频道的 HTTP 请求将自动进行。</p>
<p>启用广播时，Laravel 会自动注册 <code v-pre>/broadcasting/auth</code> 路由来处理授权请求。<code v-pre>/broadcasting/auth</code> 路由会被自动放到 <code v-pre>web</code> 中间件组中。</p>
<h3 id="定义授权回调" tabindex="-1"><a class="header-anchor" href="#定义授权回调"><span>定义授权回调</span></a></h3>
<p>接下来，我们需要定义实际决定当前认证用户的逻辑，是否可以监听给定频道。这是在 <code v-pre>routes/channels.php</code> 文件中完成的，该文件由 <code v-pre>install:broadcasting</code> Artisan 命令创建。在此文件中，你可以使用 <code v-pre>Broadcast::channel</code> 方法注册频道授权回调：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders.{orderId}'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token keyword type-hint">int</span> <span class="token variable">$orderId</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span> <span class="token operator">===</span> <span class="token class-name static-context">Order</span><span class="token operator">::</span><span class="token function">findOrNew</span><span class="token punctuation">(</span><span class="token variable">$orderId</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token property">user_id</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>channel</code> 方法接受两个参数：频道的名称和一个回调函数，该回调函数返回 <code v-pre>true</code> 或 <code v-pre>false</code> 以指示用户是否有权在频道上进行监听。</p>
<p>所有的授权回调函数都会收到当前认证的用户作为其第一个参数，以及任何额外的通配符参数作为其后续参数。在这个例子中，我们使用 <code v-pre>{orderId}</code> 占位符来表示通道名中的「ID」部分是一个通配符。</p>
<p>你可以使用 <code v-pre>channel:list</code> Artisan 命令查看应用程序的广播授权回调列表：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan channel:list</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="授权回调模型绑定" tabindex="-1"><a class="header-anchor" href="#授权回调模型绑定"><span>授权回调模型绑定</span></a></h4>
<p>就像 HTTP 路由一样，通道路由也可以利用隐式和显式<a href="https://learnku.com/docs/laravel/11.x/routingmd#route-model-binding" target="_blank" rel="noopener noreferrer">路由模型绑定</a>。例如，你可以请求一个实际的 <code v-pre>Order</code> 模型实例，而不是接收一个字符串或数字的订单 ID：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Order</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders.{order}'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token class-name type-declaration">Order</span> <span class="token variable">$order</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span> <span class="token operator">===</span> <span class="token variable">$order</span><span class="token operator">-></span><span class="token property">user_id</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
不同于 HTTP 路由模型绑定，通道模型绑定不支持自动<a href="https://learnku.com/docs/laravel/11.x/routingmd#implicit-model-binding-scoping" target="_blank" rel="noopener noreferrer">隐式模型绑定范围</a>。然而，这通常不是问题，因为大多数通道可以基于单个模型的唯一主键进行作用域限定。</p>
</blockquote>
<h4 id="授权回调验证" tabindex="-1"><a class="header-anchor" href="#授权回调验证"><span>授权回调验证</span></a></h4>
<p>私有和存在的广播频道通过你应用程序的默认身份验证守卫对当前用户进行验证。如果用户没有认证，通道授权将被自动拒绝，授权回调将不会被执行。但是，你可以指定多个自定义守卫，以根据需要对传入请求进行验证：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'channel'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'guards'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'web'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'admin'</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="定义频道类" tabindex="-1"><a class="header-anchor" href="#定义频道类"><span>定义频道类</span></a></h3>
<p>如果你的应用程序正在处理许多不同的频道，你的 <code v-pre>routes/channels.php</code> 文件可能会变得很大。所以，你可以使用频道类而不是使用闭包来授权频道。使用 <code v-pre>make:channel</code> Artisan 命令可以生成一个频道类。这个命令会将一个新的频道类放在 <code v-pre>App/Broadcasting</code> 目录下。</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan make:channel OrderChannel</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>接下来，在你的 <code v-pre>routes/channels.php</code> 文件中注册你的频道：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>OrderChannel</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders.{order}'</span><span class="token punctuation">,</span> <span class="token class-name static-context">OrderChannel</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>最后，你可以将你的频道的授权逻辑放在频道类的 <code v-pre>join</code> 方法中。这个 <code v-pre>join</code> 方法将包含你通常会放在你的频道授权闭包中的相同逻辑。你也可以利用频道模型绑定：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Broadcasting</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Order</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">OrderChannel</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 创建一个新的频道实例。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__construct</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 验证用户对频道的访问权限。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">join</span><span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token class-name type-declaration">Order</span> <span class="token variable">$order</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span><span class="token operator">|</span><span class="token keyword type-declaration">bool</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span> <span class="token operator">===</span> <span class="token variable">$order</span><span class="token operator">-></span><span class="token property">user_id</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
像 Laravel 中的许多其他类一样，频道类会被 <a href="https://learnku.com/docs/laravel/11.x/containermd" target="_blank" rel="noopener noreferrer">服务容器</a>自动解析。所以，你可以在其构造函数中对频道所需的任何依赖进行类型提示。</p>
</blockquote>
<h2 id="广播事件" tabindex="-1"><a class="header-anchor" href="#广播事件"><span>广播事件</span></a></h2>
<p>一旦你定义了一个事件并用 <code v-pre>ShouldBroadcast</code> 接口进行了标记，你就只需要使用事件的 <code v-pre>dispatch</code> 方法触发事件。事件调度器会注意到事件标记了 <code v-pre>ShouldBroadcast</code> 接口，并将事件排入广播队列：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Events<span class="token punctuation">\</span>OrderShipmentStatusUpdated</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">OrderShipmentStatusUpdated</span><span class="token operator">::</span><span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token variable">$order</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="只发给其他人" tabindex="-1"><a class="header-anchor" href="#只发给其他人"><span>只发给其他人</span></a></h3>
<p>在构建一个利用事件广播的应用程序时，你可能偶尔需要将事件广播给除当前用户之外的给定频道的所有订阅者。你可以使用 <code v-pre>broadcast</code> 辅助函数和 <code v-pre>toOthers</code> 方法来完成这个任务：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Events<span class="token punctuation">\</span>OrderShipmentStatusUpdated</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token function">broadcast</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">OrderShipmentStatusUpdated</span><span class="token punctuation">(</span><span class="token variable">$update</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">toOthers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>为了更好地理解何时可能需要使用 <code v-pre>toOthers</code> 方法，让我们设想一个任务列表应用程序，用户可以通过输入任务名称创建新任务。要创建一个任务，你的应用程序可能会向 <code v-pre>/task</code> URL 发起请求，该请求会广播任务的创建并返回新任务的 JSON 表示。当你的 JavaScript 应用程序接收到来自终端的响应时，它可能会直接将新任务插入到其任务列表中，如下所示：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">axios<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/task'</span><span class="token punctuation">,</span> task<span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">this</span><span class="token punctuation">.</span>tasks<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然而，别忘了我们也广播了任务的创建。如果你的 JavaScript 应用程序也在监听此事件以便将任务添加到任务列表，则你的列表中将有重复的任务：一个来自终点，一个来自广播。你可以通过使用 <code v-pre>toOthers</code> 方法来指示广播器不向当前用户广播事件来解决这个问题。</p>
<blockquote>
<p><strong>注意</strong><br>
要调用 <code v-pre>toOthers</code> 方法，你的事件必须使用 <code v-pre>Illuminate\Broadcasting\InteractsWithSockets</code> 特性。</p>
</blockquote>
<h4 id="配置-1" tabindex="-1"><a class="header-anchor" href="#配置-1"><span>配置</span></a></h4>
<p>当你初始化一个 Laravel Echo 实例时，一个套接字 ID 将被分配给链接。如果你正在使用全局 <a href="https://github.com/mzabriskie/axios" target="_blank" rel="noopener noreferrer">Axios</a> 实例从你的 JavaScript 应用程序中进行 HTTP 请求，套接字 ID 将自动附加到每一个发出的请求作为一个 <code v-pre>X-Socket-ID</code> 头。然后，当你调用 <code v-pre>toOthers</code> 方法时，Laravel 将从头中提取套接字 ID，并指示广播者不向具有该套接字 ID 的任何连接广播。</p>
<p>如果你没有使用全局 Axios 实例，你将需要手动配置你的 JavaScript 应用程序以在所有发出的请求中发送 <code v-pre>X-Socket-ID</code> 头。你可以使用 <code v-pre>Echo.socketId</code> 方法获取套接字 ID：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line"><span class="token keyword">var</span> socketId <span class="token operator">=</span> Echo<span class="token punctuation">.</span><span class="token function">socketId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="自定义连接" tabindex="-1"><a class="header-anchor" href="#自定义连接"><span>自定义连接</span></a></h3>
<p>如果你的应用程序与多个广播连接进行交互，你想使用一个其他广播者广播事件，你可以使用 <code v-pre>via</code> 方法指定将事件推送到哪个连接：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Events<span class="token punctuation">\</span>OrderShipmentStatusUpdated</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token function">broadcast</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">OrderShipmentStatusUpdated</span><span class="token punctuation">(</span><span class="token variable">$update</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">via</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'pusher'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>或者，你可以通过在事件的构造函数中调用 <code v-pre>broadcastVia</code> 方法来指定事件的广播连接。然而，在这样做之前，你应该确保事件类使用了 <code v-pre>InteractsWithBroadcasting</code> Trait：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Events</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>Channel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>InteractsWithBroadcasting</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>InteractsWithSockets</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PresenceChannel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PrivateChannel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>ShouldBroadcast</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Queue<span class="token punctuation">\</span>SerializesModels</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">OrderShipmentStatusUpdated</span> <span class="token keyword">implements</span> <span class="token class-name">ShouldBroadcast</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">InteractsWithBroadcasting</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 创建一个新的事件实例。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__construct</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">broadcastVia</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'pusher'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="匿名事件广播" tabindex="-1"><a class="header-anchor" href="#匿名事件广播"><span>匿名事件广播</span></a></h3>
<p>有时，你可能希望在不创建专用事件类的情况下，向应用程序的前端广播一个简单的事件。为了满足这一需求，<code v-pre>Broadcast</code> facade 允许你广播「匿名事件」：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders.'</span><span class="token operator">.</span><span class="token variable">$order</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>上面的示例将广播以下事件：</p>
<div class="language-json line-numbers-mode" data-highlighter="prismjs" data-ext="json" data-title="json"><pre v-pre class="language-json"><code><span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token property">"event"</span><span class="token operator">:</span> <span class="token string">"AnonymousEvent"</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token property">"data"</span><span class="token operator">:</span> <span class="token string">"[]"</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token property">"channel"</span><span class="token operator">:</span> <span class="token string">"orders.1"</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>使用 <code v-pre>as</code> 和 <code v-pre>with</code> 方法，你可以自定义事件的名称和数据：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders.'</span><span class="token operator">.</span><span class="token variable">$order</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">as</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'OrderPlaced'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">with</span><span class="token punctuation">(</span><span class="token variable">$order</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>上面的示例将广播如下事件：</p>
<div class="language-json line-numbers-mode" data-highlighter="prismjs" data-ext="json" data-title="json"><pre v-pre class="language-json"><code><span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token property">"event"</span><span class="token operator">:</span> <span class="token string">"OrderPlaced"</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token property">"data"</span><span class="token operator">:</span> <span class="token string">"{ id: 1, total: 100 }"</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token property">"channel"</span><span class="token operator">:</span> <span class="token string">"orders.1"</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你希望在私有频道或存在频道上广播匿名事件，你可以使用 <code v-pre>private</code> 和 <code v-pre>presence</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">private</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders.'</span><span class="token operator">.</span><span class="token variable">$order</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">presence</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'channels.'</span><span class="token operator">.</span><span class="token variable">$channel</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>使用 <code v-pre>send</code> 方法广播匿名事件会将事件分派到你应用程序的<a href="https://learnku.com/docs/laravel/11.x/queuesmd" target="_blank" rel="noopener noreferrer">队列</a>中进行处理。但是，如果你希望立即广播事件，可以使用 <code v-pre>sendNow</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders.'</span><span class="token operator">.</span><span class="token variable">$order</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">sendNow</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>要向除当前认证用户以外的所有频道订阅者广播事件，你可以调用 <code v-pre>toOthers</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'orders.'</span><span class="token operator">.</span><span class="token variable">$order</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">toOthers</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="接收广播" tabindex="-1"><a class="header-anchor" href="#接收广播"><span>接收广播</span></a></h2>
<h3 id="监听事件" tabindex="-1"><a class="header-anchor" href="#监听事件"><span>监听事件</span></a></h3>
<p>一旦你<a href="#client-side-installation">安装并实例化了 Laravel Echo</a>，你就可以开始监听来自你的 Laravel 应用程序广播的事件了。首先，使用 <code v-pre>channel</code> 方法获取频道的一个实例，然后调用 <code v-pre>listen</code> 方法来开始监听指定的事件</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">orders.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>order<span class="token punctuation">.</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string">'OrderShipmentStatusUpdated'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>order<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你想在私有频道上监听事件，那么应使用 <code v-pre>private</code> 方法替代。你可以继续链接 <code v-pre>listen</code> 方法来在单一频道上监听多个事件：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">private</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">orders.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>order<span class="token punctuation">.</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token comment">/* ... */</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token comment">/* ... */</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token comment">/* ... */</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="停止监听事件" tabindex="-1"><a class="header-anchor" href="#停止监听事件"><span>停止监听事件</span></a></h4>
<p>如果你想在<a href="#leaving-a-channel">不离开频道</a>的情况下停止监听某个事件，你可以使用 <code v-pre>stopListening</code> 方法：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">private</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">orders.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>order<span class="token punctuation">.</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">stopListening</span><span class="token punctuation">(</span><span class="token string">'OrderShipmentStatusUpdated'</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="离开频道" tabindex="-1"><a class="header-anchor" href="#离开频道"><span>离开频道</span></a></h3>
<p>要离开频道，你可以在你的 Echo 实例上调用 <code v-pre>leaveChannel</code> 方法：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">leaveChannel</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">orders.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>order<span class="token punctuation">.</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你希望离开频道以及其关联的私有和存在频道，你可以调用 <code v-pre>leave</code> 方法：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">leave</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">orders.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>order<span class="token punctuation">.</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="命名空间" tabindex="-1"><a class="header-anchor" href="#命名空间"><span>命名空间</span></a></h3>
<p>你可能已经注意到，在上述例子中，我们没有为事件类指定完整的 <code v-pre>App\Events</code> 命名空间。这是因为 Echo 会自动假设事件位于 <code v-pre>App\Events</code> 命名空间中。但是，你可以在实例化 Echo 时通过传递 <code v-pre>namespace</code> 配置选项来配置根命名空间：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">window<span class="token punctuation">.</span>Echo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Echo</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    <span class="token literal-property property">broadcaster</span><span class="token operator">:</span> <span class="token string">'pusher'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line">    <span class="token literal-property property">namespace</span><span class="token operator">:</span> <span class="token string">'App.Other.Namespace'</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>或者，当你使用 Echo 订阅它们时，你可以为事件类使用 <code v-pre>.</code> 前缀。这将允许你始终指定完全限定的类名：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string">'orders'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string">'.Namespace\\Event\\Class'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="presence-频道" tabindex="-1"><a class="header-anchor" href="#presence-频道"><span>Presence 频道</span></a></h2>
<p>Presence 频道基于私有频道的安全性，同时暴露了关于谁订阅了频道的额外功能。这使得构建强大的，协作的应用程序功能变得容易，例如当另一个用户正在浏览同一页面时通知用户或者列出聊天室的成员。</p>
<h3 id="授权存在频道" tabindex="-1"><a class="header-anchor" href="#授权存在频道"><span>授权存在频道</span></a></h3>
<p>所有的存在频道也都是私有频道；因此，用户必须被<a href="#authorizing-channels">授权访问他们</a>。然而，当为 存在频道定义授权回调时，如果用户被授权加入频道，你将不会返回 <code v-pre>true</code>。相反，你应该返回一组关于用户的数据。</p>
<p>这些由授权回调返回的数据，将在你的 JavaScript 应用中的存在频道事件侦听器中可用。如果用户未被授权加入存在频道，你应返回 <code v-pre>false</code> 或 <code v-pre>null</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token class-name static-context">Broadcast</span><span class="token operator">::</span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'chat.{roomId}'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">User</span> <span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token keyword type-hint">int</span> <span class="token variable">$roomId</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">canJoinRoom</span><span class="token punctuation">(</span><span class="token variable">$roomId</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'id'</span> <span class="token operator">=></span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'name'</span> <span class="token operator">=></span> <span class="token variable">$user</span><span class="token operator">-></span><span class="token property">name</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="加入存在频道" tabindex="-1"><a class="header-anchor" href="#加入存在频道"><span>加入存在频道</span></a></h3>
<p>为了加入存在频道，你可以使用 Echo 的 <code v-pre>join</code> 方法。<code v-pre>join</code> 方法将返回一个 <code v-pre>PresenceChannel</code> 实现，这个实现，以及暴露 <code v-pre>listen</code> 方法，允许你订阅 <code v-pre>here</code>，<code v-pre>joining</code> 和 <code v-pre>leaving</code> 事件。</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">chat.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>roomId<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">here</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">users</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">joining</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">user</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">leaving</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">user</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">error</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span>error<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当频道成功加入后 <code v-pre>here</code> 回调将立即执行，且会接收一个数组，此数组含有所有当前订阅频道的其他用户的用户信息。当新用户加入频道时，将执行 <code v-pre>joining</code> 方法；当用户离开频道时，将执行 <code v-pre>leaving</code> 方法。如果认证端点返回的 HTTP 状态码不是 200 或解析返回的 JSON 数据出现问题，那么将执行 error 方法。</p>
<h3 id="对存在频道进行广播" tabindex="-1"><a class="header-anchor" href="#对存在频道进行广播"><span>对存在频道进行广播</span></a></h3>
<p>存在频道可以像公共或私有频道一样接收事件。使用聊天室作为例子，我们可能希望广播 <code v-pre>NewMessage</code> 事件给房间的存在频道。为了实现这个，我们将从事件的 <code v-pre>broadcastOn</code> 方法返回一个 <code v-pre>PresenceChannel</code> 实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取应该广播的频道。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;int, \Illuminate\Broadcasting\Channel></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastOn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token keyword">new</span> <span class="token class-name">PresenceChannel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'chat.'</span><span class="token operator">.</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">message</span><span class="token operator">-></span><span class="token property">room_id</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>就像其他事件一样，你可以使用 <code v-pre>broadcast</code> 辅助函数和 <code v-pre>toOthers</code> 方法来排除当前用户接收广播：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token function">broadcast</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">NewMessage</span><span class="token punctuation">(</span><span class="token variable">$message</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token function">broadcast</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">NewMessage</span><span class="token punctuation">(</span><span class="token variable">$message</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">toOthers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>和其他类型的事件一样，你可以使用 Echo 的 <code v-pre>listen</code> 方法来监听发送到存在频道的事件：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">chat.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>roomId<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">here</span><span class="token punctuation">(</span><span class="token comment">/* ... */</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">joining</span><span class="token punctuation">(</span><span class="token comment">/* ... */</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">leaving</span><span class="token punctuation">(</span><span class="token comment">/* ... */</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string">'NewMessage'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="模型广播" tabindex="-1"><a class="header-anchor" href="#模型广播"><span>模型广播</span></a></h2>
<blockquote>
<p><strong>注意</strong><br>
在阅读以下关于模型广播的文档之前，我们建议你熟悉 Laravel 的模型广播服务的一般概念以及如何手动创建和监听广播事件。</p>
</blockquote>
<p>当你的应用程序的 <a href="https://learnku.com/docs/laravel/11.x/eloquentmd" target="_blank" rel="noopener noreferrer">Eloquent 模型</a> 创建、更新或删除时，通常会广播事件。当然，这可以通过手动<a href="https://learnku.com/docs/laravel/11.x/eloquentmd#events" target="_blank" rel="noopener noreferrer">为 Eloquent 模型状态变更定义自定义事件</a>并标记这些事件，这可以使用 <code v-pre>ShouldBroadcast</code> 接口来轻松实现。</p>
<p>然而，如果你在应用程序中没有为了其他目的使用这些事件，那么为了仅仅广播它们而创建事件类可能会很麻烦。为了解决这个问题，Laravel 允许你表明一个 Eloquent 模型应自动广播其状态变更。</p>
<p>首先，你的 Eloquent 模型应使用 <code v-pre>Illuminate\Database\Eloquent\BroadcastsEvents</code> Trait。此外，该模型应定义一个 <code v-pre>broadcastOn</code> 的方法，该方法将返回模型事件应广播频道的数组：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>Channel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PrivateChannel</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>BroadcastsEvents</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Factories<span class="token punctuation">\</span>HasFactory</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Relations<span class="token punctuation">\</span>BelongsTo</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Post</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">BroadcastsEvents</span><span class="token punctuation">,</span> HasFactory<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 获取发帖用户</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">user</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">BelongsTo</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">belongsTo</span><span class="token punctuation">(</span><span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 取模型事件应该广播的频道</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;int, \Illuminate\Broadcasting\Channel|\Illuminate\Database\Eloquent\Model></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastOn</span><span class="token punctuation">(</span><span class="token keyword type-hint">string</span> <span class="token variable">$event</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token variable">$this</span><span class="token punctuation">,</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">user</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>一旦你的模型引入了这个特质并定义了其广播频道，它就会在模型实例被创建、更新、删除、移到回收站或还原时开始自动广播事件。</p>
<p>另外，你可能注意到 <code v-pre>broadcastOn</code> 方法接收了一个字符串 <code v-pre>$event</code> 参数。这个参数包含了模型发生的事件类型并将具有 <code v-pre>created</code>，<code v-pre>updated</code>，<code v-pre>deleted</code>，<code v-pre>trashed</code> 或 <code v-pre>restored</code> 的值。通过检查这个变量的值，你可以确定模型应对哪个特定事件广播哪个频道（如果有的话）：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取模型事件应该广播的频道</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;string, array&lt;int, \Illuminate\Broadcasting\Channel|\Illuminate\Database\Eloquent\Model>></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastOn</span><span class="token punctuation">(</span><span class="token keyword type-hint">string</span> <span class="token variable">$event</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token keyword">match</span> <span class="token punctuation">(</span><span class="token variable">$event</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token string single-quoted-string">'deleted'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token keyword">default</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token variable">$this</span><span class="token punctuation">,</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">user</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="自定义模型广播事件创建" tabindex="-1"><a class="header-anchor" href="#自定义模型广播事件创建"><span>自定义模型广播事件创建</span></a></h4>
<p>偶尔，你可能希望自定义 Laravel 如何创建底层的模型广播事件。你可以通过在你的 Eloquent 模型中定义一个 <code v-pre>newBroadcastableEvent</code> 方法来实现这一点。这个方法应该返回一个 <code v-pre>Illuminate\Database\Eloquent\BroadcastableModelEventOccurred</code> 实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>BroadcastableModelEventOccurred</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 为该模型创建一个新的可广播的模型事件。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">protected</span> <span class="token keyword">function</span> <span class="token function-definition function">newBroadcastableEvent</span><span class="token punctuation">(</span><span class="token keyword type-hint">string</span> <span class="token variable">$event</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">BroadcastableModelEventOccurred</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">BroadcastableModelEventOccurred</span><span class="token punctuation">(</span></span>
<span class="line">        <span class="token variable">$this</span><span class="token punctuation">,</span> <span class="token variable">$event</span></span>
<span class="line">    <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">dontBroadcastToCurrentUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="模型广播约定" tabindex="-1"><a class="header-anchor" href="#模型广播约定"><span>模型广播约定</span></a></h3>
<h4 id="频道约定" tabindex="-1"><a class="header-anchor" href="#频道约定"><span>频道约定</span></a></h4>
<p>你可能已经注意到，上面模型示例中的 <code v-pre>broadcastOn</code> 方法并没有返回 <code v-pre>Channel</code> 实例。相反，直接返回了 Eloquent 模型。如果你的模型的 <code v-pre>broadcastOn</code> 方法返回了一个 Eloquent 模型实例（或者该方法返回的数组中包含了一个 Eloquent 模型实例），Laravel 将自动为模型实例化一个私有频道，使用模型的类名和主键标识符作为频道名称。</p>
<p>所以，一个 <code v-pre>id</code> 为 <code v-pre>1</code> 的 <code v-pre>App\Models\User</code> 模型将会被转换为一个名称为 <code v-pre>App.Models.User.1</code> 的 <code v-pre>Illuminate\Broadcasting\PrivateChannel</code> 实例。当然，你可以在你的模型 <code v-pre>broadcastOn</code> 方法中返回完整的 <code v-pre>Channel</code> 实例，以完全控制模型的频道名称：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Broadcasting<span class="token punctuation">\</span>PrivateChannel</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取模型事件应广播的频道。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;int, \Illuminate\Broadcasting\Channel></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastOn</span><span class="token punctuation">(</span><span class="token keyword type-hint">string</span> <span class="token variable">$event</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token keyword">new</span> <span class="token class-name">PrivateChannel</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'user.'</span><span class="token operator">.</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">id</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你打算从模型的 <code v-pre>broadcastOn</code> 方法中显式返回一个频道实例，你可以将一个 Eloquent 模型实例传递给频道的构造器。这样做的时候，Laravel 将使用上述的模型频道约定把 Eloquent 模型转换为频道名称字符串：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token keyword">new</span> <span class="token class-name">Channel</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">user</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你需要确定模型的频道名称，你可以在任何模型实例上调用 <code v-pre>broadcastChannel</code> 方法。例如，这个方法会对一个 <code v-pre>id</code> 为 <code v-pre>1</code> 的 <code v-pre>App\Models\User</code> 模型返回字符串 <code v-pre>App.Models.User.1</code> ：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$user</span><span class="token operator">-></span><span class="token function">broadcastChannel</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="事件约定" tabindex="-1"><a class="header-anchor" href="#事件约定"><span>事件约定</span></a></h4>
<p>由于模型广播事件不关联你应用程序的 <code v-pre>App\Events</code> 目录中的「实际」事件，因此他们根据约定分配了一个名称和载荷。 Laravel 的约定是使用模型的类名（不包括命名空间）和触发广播的模型事件的名称来广播事件。</p>
<p>因此，例如，对 <code v-pre>App\Models\Post</code> 模型的更新将广播一个事件名为 <code v-pre>PostUpdated</code> 的事件，载荷如下：</p>
<div class="language-json line-numbers-mode" data-highlighter="prismjs" data-ext="json" data-title="json"><pre v-pre class="language-json"><code><span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token property">"model"</span><span class="token operator">:</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token property">"id"</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token property">"title"</span><span class="token operator">:</span> <span class="token string">"My first post"</span></span>
<span class="line">        ...</span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">,</span></span>
<span class="line">    ...</span>
<span class="line">    <span class="token property">"socket"</span><span class="token operator">:</span> <span class="token string">"someSocketId"</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>App\Models\User</code> 的删除将广播一个名为 <code v-pre>UserDeleted</code> 的事件。</p>
<p>如果你愿意，你可以通过在模型中添加一个 <code v-pre>broadcastAs</code> 和 <code v-pre>broadcastWith</code> 方法来定义自定义的广播名称和载荷。这些方法接收模型事件 / 操作的名称，允许你为每个模型操作自定义事件的名称和载荷。如果 <code v-pre>broadcastAs</code> 方法返回 <code v-pre>null</code> ，Laravel 将使用上述的模型广播事件名称约定进行广播事件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 模型事件的广播名称。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastAs</span><span class="token punctuation">(</span><span class="token keyword type-hint">string</span> <span class="token variable">$event</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">string</span><span class="token operator">|</span><span class="token keyword type-declaration">null</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token keyword">match</span> <span class="token punctuation">(</span><span class="token variable">$event</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token string single-quoted-string">'created'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'post.created'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token keyword">default</span> <span class="token operator">=></span> <span class="token constant">null</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取模型的广播数据。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;string, mixed></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">broadcastWith</span><span class="token punctuation">(</span><span class="token keyword type-hint">string</span> <span class="token variable">$event</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token keyword">match</span> <span class="token punctuation">(</span><span class="token variable">$event</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token string single-quoted-string">'created'</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'title'</span> <span class="token operator">=></span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">title</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token keyword">default</span> <span class="token operator">=></span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'model'</span> <span class="token operator">=></span> <span class="token variable">$this</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="监听模型广播" tabindex="-1"><a class="header-anchor" href="#监听模型广播"><span>监听模型广播</span></a></h3>
<p>一旦你向你的模型中添加了 <code v-pre>BroadcastsEvents</code> Trait，并定义了你的模型的 <code v-pre>broadcastOn</code> 方法，你就可以开始在你的客户端应用中监听广播的模型事件了。在开始之前，你可能需要查阅关于<a href="#listening-for-events">监听事件</a>的完整文档。</p>
<p>首先，使用 <code v-pre>private</code> 方法来获取一个频道实例，然后调用 <code v-pre>listen</code> 方法来监听某个特定的事件。通常，给 <code v-pre>private</code> 方法的频道名应该对应 Laravel 的<a href="#model-broadcasting-conventions">模型广播约定</a>。</p>
<p>获取到频道实例之后，你可以使用 <code v-pre>listen</code> 方法来监听一个特定的事件。由于模型广播事件不关联应用程序的 <code v-pre>App\Events</code> 目录中的「实际」事件，所以<a href="#model-broadcasting-event-conventions">事件名称</a>必须以 <code v-pre>.</code> 作前缀，指出它不属于特定的名称空间。每个模型广播事件都有一个 <code v-pre>model</code> 属性，包含所有模型的可广播属性：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">private</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">App.Models.User.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>user<span class="token punctuation">.</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string">'.PostUpdated'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>model<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="客户端事件" tabindex="-1"><a class="header-anchor" href="#客户端事件"><span>客户端事件</span></a></h2>
<blockquote>
<p><strong>注意</strong><br>
使用<a href="https://pusher.com/channels" target="_blank" rel="noopener noreferrer">Pusher Channels</a>时，要发送客户端事件，你必须在<a href="https://dashboard.pusher.com/" target="_blank" rel="noopener noreferrer">应用管理板</a>的「应用程序设置」部分启用 「客户端事件」选项。</p>
</blockquote>
<p>有时你可能希望将事件广播给其他连接的客户端，而根本不会触发你的 Laravel 应用程序。这对于诸如「正在输入」 通知非常有用，其中你希望向应用程序的用户通知另一个用户正在给定屏幕上输入消息。</p>
<p>为了广播客户端事件，你可以使用 Echo 的 <code v-pre>whisper</code> 方法：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">private</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">chat.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>roomId<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">whisper</span><span class="token punctuation">(</span><span class="token string">'typing'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>user<span class="token punctuation">.</span>name</span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>为了监听客户端事件，你可以使用 <code v-pre>listenForWhisper</code> 方法：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">private</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">chat.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>roomId<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">listenForWhisper</span><span class="token punctuation">(</span><span class="token string">'typing'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="通知" tabindex="-1"><a class="header-anchor" href="#通知"><span>通知</span></a></h2>
<p>通过配对事件广播和<a href="https://learnku.com/docs/laravel/11.x/notificationsmd" target="_blank" rel="noopener noreferrer">通知</a>，你的 JavaScript 应用在通知发生时可以收到新的通知，而无需刷新页面。在开始之前，请务必阅读了解如何使用<a href="https://learnku.com/docs/laravel/11.x/notificationsmd#broadcast-notifications" target="_blank" rel="noopener noreferrer">广播通知频道</a>。</p>
<p>一旦你配置一个通知使用广播频道，你就可以使用 Echo 的 <code v-pre>notification</code> 方法来监听广播的事件了。请注意，频道名应该匹配接收通知的实体的类名：</p>
<div class="language-javascript line-numbers-mode" data-highlighter="prismjs" data-ext="js" data-title="js"><pre v-pre class="language-javascript"><code><span class="line">Echo<span class="token punctuation">.</span><span class="token function">private</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">App.Models.User.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>userId<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">.</span><span class="token function">notification</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">notification</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></span>
<span class="line">        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>notification<span class="token punctuation">.</span>type<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在这个例子，所有通过 <code v-pre>broadcast</code> 频道发送给 <code v-pre>App\Models\User</code> 实例的通知会被回调得到。应用的 <code v-pre>routes/channels.php</code> 文件中已经包含了 <code v-pre>App.Models.User.{id}</code> 频道的授权回调。</p>
<blockquote>
<p>本译文仅用于学习和交流目的，转载请务必注明文章译者、出处、和本文链接<br>
我们的翻译工作遵照 <a href="https://learnku.com/docs/guide/cc4.0/6589" target="_blank" rel="noopener noreferrer">CC 协议</a>，如果我们的工作有侵犯到您的权益，请及时联系我们。</p>
</blockquote>
<hr>
<blockquote>
<p>原文地址：<a href="https://learnku.com/docs/laravel/11.x/broadcastingmd/16672" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/br...</a></p>
<p>译文地址：<a href="https://learnku.com/docs/laravel/11.x/broadcastingmd/16672" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/br...</a></p>
</blockquote>
</div></template>


